﻿namespace MicroCloud.Message
{
    /// <summary>
    /// 业务实现：消息服务
    /// </summary>
    public class MessageService : IMessageService
    {
        /// <summary>
        /// 初始化一个消息服务 <see cref="MessageService"/> 的新实例
        /// </summary>
        /// <param name="provider">服务提供者</param>
        public MessageService(IServiceProvider provider)
        {
            ServiceProvider = provider;
        }

        #region 属性
        /// <summary>
        /// 获取 服务提供者
        /// </summary>
        protected IServiceProvider ServiceProvider { get; }

        /// <summary>
        /// 获取 日志记录器
        /// </summary>
        protected ILogger Logger => ServiceProvider.GetLogger<MessageService>();

        /// <summary>
        /// 获取 事件总线
        /// </summary>
        protected IEventBus EventBus => ServiceProvider.GetService<IEventBus>();

        /// <summary>
        /// 获取 通信连接用户缓存
        /// </summary>
        protected IConnectionUserCache UserCache => ServiceProvider.GetService<IConnectionUserCache>();

        /// <summary>
        /// 获取 当前用户的基本功能
        /// </summary>
        protected IPrincipal Principal => ServiceProvider.GetService<IPrincipal>();

        /// <summary>
        /// 获取 用户管理功能
        /// </summary>
        protected UserManager<User> UserManager => ServiceProvider.GetService<UserManager<User>>();

        /// <summary>
        /// 获取 角色管理功能
        /// </summary>
        protected RoleManager<Role> RoleManager => ServiceProvider.GetService<RoleManager<Role>>();

        /// <summary>
        /// 获取 身份认证模块
        /// </summary>
        protected IIdentityContract IdentityContract => ServiceProvider.GetService<IIdentityContract>();

        /// <summary>
        /// 获取 SignalR服务
        /// </summary>
        protected ISignalRService SignalRService => ServiceProvider.GetService<ISignalRService>();

        /// <summary>
        /// 获取 消息仓储模型
        /// </summary>
        protected IRepository<MessageEntity, long> MessageRepository => ServiceProvider.GetService<IRepository<MessageEntity, long>>();

        /// <summary>
        /// 获取 消息接收者仓储模型
        /// </summary>
        protected IRepository<MessageReceiver, long> MessageReceiverRepository => ServiceProvider.GetService<IRepository<MessageReceiver, long>>();

        /// <summary>
        /// 获取 模板消息仓储模型
        /// </summary>
        protected IRepository<TemplateMessage, long> TemplateMessageRepository => ServiceProvider.GetService<IRepository<TemplateMessage, long>>();

        /// <summary>
        /// 获取 消息查询数据集
        /// </summary>
        public virtual IQueryable<MessageEntity> Messages => MessageRepository.QueryAsNoTracking();
 
        /// <summary>
        /// 获取 消息接收者查询数据集
        /// </summary>
        public virtual IQueryable<MessageReceiver> MessageReceivers => MessageReceiverRepository.QueryAsNoTracking();

        /// <summary>
        /// 获取 模板消息查询数据集
        /// </summary>
        public virtual IQueryable<TemplateMessage> TemplateMessages => TemplateMessageRepository.QueryAsNoTracking();

        #endregion

        #region 方法
        #region "创建消息"
        /// <summary>
        /// 创建消息
        /// </summary>
        /// <param name="dtos">消息DTO</param>
        /// <returns>业务操作结果</returns>
        public virtual async Task<OperationResult> CreateMessages(params MessageInputDto[] dtos)
        {
            Check.NotNull(dtos, nameof(dtos));
            MessageEventData eventData = new(SignalRService?.SignalRHub?.Clients, SignalRService?.SignalRHub?.Groups) { OperateType = OperateType.Insert };
            foreach (var dto in dtos)
            {
                Check.NotNull(dto, nameof(dto));
                Check.NotNullOrEmpty(dto.Title, nameof(dto.Title));

                Check.GreaterThan(dto.StorageDays, nameof(dto.StorageDays), 0, true);
                Check.LessThan(dto.StorageDays, nameof(dto.StorageDays), 365, true);

                if (dto.BaseType.IsMissing())
                {
                    var method = "MSG_NOTICE";
                    dto.Method = method;
                }
                Check.NotNullOrEmpty(dto.Method, nameof(dto.Method));

                var dateTimeNow = DateTime.Now;
                dto.SendTime = dto.SendTime == default ? dateTimeNow : dto.SendTime;
                var entity = dto.MapTo<MessageInputDto, MessageEntity>();
                //获取当前用户
                if (Principal?.Identity?.IsAuthenticated == true)
                {
                    entity.SenderId = GetCurrentUserKey();
                    entity.IsSystem = false;
                }
                else
                {
                    entity.SenderId = null;
                    entity.IsSystem = true;
                }
                //设置是否立即发送
                TimeSpan timeSpan = new(entity.SendTime.Ticks - dateTimeNow.Ticks);
                if (timeSpan.TotalMinutes <= 1)
                {
                    entity.SendTime = dateTimeNow;
                    entity.IsSent = true;
                }
                else
                {
                    entity.IsSent = false;
                }
                IUnitOfWork unitOfWork = ServiceProvider.GetUnitOfWork(true);
                //处理消息创建
                var result = await MessageRepository.InsertAsync(entity);
                if (!result.Succeeded)
                {
                    return result;
                }
                //处理消息发送
                if (entity.IsSent)
                {
                    result = await SendMessages(entity.Id);
                    if (!result.Succeeded)
                    {
                        return result;
                    }
                }
                await unitOfWork.CommitAsync();

                //处理消息事件数据
                eventData.Messages.Add(entity);
            }
            //触发事件
            if (eventData.Messages.Count > 0)
            {
                await EventBus?.PublishAsync(eventData);
            }

            return OperationResult.Success();
        }
        #endregion
        #region "更新消息"
        /// <summary>
        /// 更新消息
        /// </summary>
        /// <param name="dtos">消息DTO</param>
        /// <returns>业务操作结果</returns>
        public virtual async Task<OperationResult> UpdateMessages(params MessageInputDto[] dtos)
        {
            Check.NotNull(dtos, nameof(dtos));
            MessageEventData eventData = new(SignalRService?.SignalRHub?.Clients, SignalRService?.SignalRHub?.Groups) { OperateType = OperateType.Update };
            foreach (var dto in dtos)
            {
                Check.NotNull(dto, nameof(dto));
                Check.NotNullOrEmpty(dto.Title, nameof(dto.Title));

                Check.GreaterThan(dto.StorageDays, nameof(dto.StorageDays), 0, true);
                Check.LessThan(dto.StorageDays, nameof(dto.StorageDays), 365, true);

                if (dto.BaseType.IsMissing() && dto.Method.IsMissing())
                {
                    var method = "MSG_NOTICE";
                    dto.Method = method;
                }
                Check.NotNullOrEmpty(dto.Method, nameof(dto.Method));

                var dateTimeNow = DateTime.Now;
                dto.SendTime = dto.SendTime == default ? dateTimeNow : dto.SendTime;

                var entity = await MessageRepository.GetAsync(dto.Id);
                if (entity == null)
                {
                    return OperationResult.Error(I18N.T("消息 {0} 不存在", dto.Id));
                }
                if (entity.IsSent)
                {
                    return OperationResult.Error(I18N.T("消息 {0} 已发送，不允许更新。", dto.Id));
                }
                entity = dto.MapTo(entity);

                //获取当前用户
                if (Principal?.Identity?.IsAuthenticated == true)
                {
                    entity.SenderId = GetCurrentUserKey();
                    entity.IsSystem = false;
                }
                else
                {
                    entity.SenderId = null;
                    entity.IsSystem = true;
                }
                //设置是否立即发送
                TimeSpan timeSpan = new(entity.SendTime.Ticks - dateTimeNow.Ticks);
                if (timeSpan.TotalMinutes <= 1)
                {
                    entity.SendTime = dateTimeNow;
                    entity.IsSent = true;
                }
                else
                {
                    entity.IsSent = false;
                }
                //处理消息更新
                var result = await MessageRepository.UpdateAsync(entity);
                if (!result.Succeeded)
                {
                    return result;
                }
                //处理消息发送
                if (entity.IsSent)
                {
                    result = await SendMessages(entity.Id);
                    if (!result.Succeeded)
                    {
                        return result;
                    }
                }

                //处理消息事件数据
                eventData.Messages.Add(entity);
            }
            //触发事件
            if (eventData.Messages.Count > 0)
            {
                await EventBus?.PublishAsync(eventData);
            }

            return OperationResult.Success();
        }
        #endregion
        #region "删除消息"
        /// <summary>
        /// 删除消息
        /// </summary>
        /// <param name="ids">消息编号</param>
        /// <returns>业务操作结果</returns>
        public virtual async Task<OperationResult> DeleteMessages(params long[] ids)
        {
            Check.NotNull(ids, nameof(ids));
            MessageEventData eventData = new(SignalRService?.SignalRHub?.Clients, SignalRService?.SignalRHub?.Groups) { OperateType = OperateType.Delete };
            foreach (var id in ids)
            {
                var entity = await MessageRepository.GetAsync(id);
                if (entity == null)
                {
                    return OperationResult.Error(I18N.T("消息 {0} 不存在", id));
                }
                //if (entity.IsSent)
                //{
                //    return OperationResult.Error(I18N.T("消息 {0} 已发送，不允许删除。", id));
                //}
                //await MessageReceiverRepository.DeleteBatchAsync(o => o.MessageId == entity.Id);  //移到删除事件处理器中进行处理
                var messageReceivers = MessageReceiverRepository.QueryAsNoTracking().Where(o => o.MessageId == entity.Id).ToList();
                var result = await MessageRepository.DeleteAsync(id);
                if (!result.Succeeded)
                {
                    return result;
                }
                //处理消息事件数据
                eventData.Messages.Add(entity);
                if (messageReceivers?.Count > 0)
                {
                    eventData.MessageReceivers.AddRange(messageReceivers);
                }
            }
            //触发事件
            if (eventData.Messages.Count > 0)
            {
                await EventBus?.PublishAsync(eventData);
            }

            return OperationResult.Success();
        }
        #endregion

        #region "发送消息"
        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="messageIds">消息编号</param>
        /// <returns>业务操作结果</returns>
        public virtual async Task<OperationResult> SendMessages(params long[] messageIds)
        {
            Check.NotNull(messageIds, nameof(messageIds));
            MessageSendEventData eventData = new(SignalRService?.SignalRHub?.Clients, SignalRService?.SignalRHub?.Groups);
            foreach (var messageId in messageIds)
            {
                Check.GreaterThan(messageId, nameof(messageId), 0);
                //移除消息发送任务
                RecurringJob.RemoveIfExists(GetMessageSendJobId(messageId.ToString()));

                var messageEntity = await MessageRepository.GetAsync(messageId);
                if (messageEntity == null)
                {
                    return OperationResult.Error(I18N.T("消息 {0} 不存在", messageId));
                }
                var messageDto = messageEntity.MapTo<MessageEntity, MessageOutputDto>();
                if (messageDto.SendWays?.Length <= 0)
                {
                    return OperationResult.Error(I18N.T("没有发送方式"));
                }
                if (messageDto.ToUsers?.Length <= 0 && messageDto.ToOrganizations?.Length <= 0 && messageDto.ToRoles?.Length <= 0)
                {
                    return OperationResult.Error(I18N.T("没有收件人信息"));
                }
                //if(entity.IsSent)
                //{
                //    return OperationResult.Error(I18N.T("消息 {0} 已发送", messageId));
                //}

                //TODO：拆分至每个用户(组转用户)后持久化数据集
                //var messageReceivers = MessageReceivers.Where(o => o.MessageId == messageId).ToList();
                await MessageReceiverRepository.DeleteBatchAsync(o => o.MessageId == messageId);
                List<User> receiverUsers = new();
                if (messageDto.ToUsers?.Length > 0)
                {
                    foreach (string toUser in messageDto.ToUsers)
                    {
                        var receiverUser = await FindUser(toUser);
                        if (receiverUser == null)
                        {
                            return OperationResult.Error(I18N.T("用户 {0} 不存在", toUser));
                        }
                        //var messageReceiver = MessageReceivers.Where(o => o.MessageId == messageId && o.ReceiverId == receiverUser.Id).FirstOrDefault();
                        receiverUsers.AddIfNotExist(receiverUser, o => receiverUsers.Exists(r => r.Id == o.Id));
                    }
                }
                if (messageDto.ToOrganizations?.Length > 0)
                {
                    var organizationProvider = ServiceProvider.GetService<IOrganizationProvider>();
                    List<long> organizationIds = new();
                    foreach (string toOrganization in messageDto.ToOrganizations)
                    {
                        var organization = organizationProvider.GetOrganizationById(toOrganization);
                        if (organization == null)
                        {
                            return OperationResult.Error(I18N.T("组织机构 {0} 不存在", toOrganization));
                        }
                        organizationIds.Add(organization.Id.CastTo<long>());

                        var childOrganizations = organizationProvider?.GetChildOrganizations(organization.Id).Select(o => o.Id.CastTo<long>()).ToList();
                        organizationIds = organizationIds.Union(childOrganizations).ToList();

                        //组织机构对应用户
                        var userEntities = IdentityContract.UserOrganizations.Where(m => organizationIds.Contains(m.OrganizationId)).Select(m => m.User).Distinct().ToArray();
                        if (userEntities?.Length > 0)
                        {
                            foreach (var userEntity in userEntities)
                            {
                                receiverUsers.AddIfNotExist(userEntity, o => receiverUsers.Exists(r => r.Id == o.Id));
                            }
                        }
                        //组织机构对应角色
                        var roleEntities = IdentityContract.RoleOrganizations.Where(m => organizationIds.Contains(m.OrganizationId)).Select(m => m.Role).Distinct().ToArray();
                        if (roleEntities?.Length > 0)
                        {
                            foreach (var roleEntity in roleEntities)
                            {
                                //角色对应用户
                                var userEntities2 = IdentityContract.UserRoles.Where(m => m.RoleId == roleEntity.Id).Select(m => m.User).Distinct().ToArray();
                                if (userEntities2?.Length > 0)
                                {
                                    foreach (var userEntity in userEntities2)
                                    {
                                        receiverUsers.AddIfNotExist(userEntity, o => receiverUsers.Exists(r => r.Id == o.Id));
                                    }
                                }
                            }
                        }
                    }
                }
                if (messageDto.ToRoles?.Length > 0)
                {
                    foreach (string toRole in messageDto.ToRoles)
                    {
                        var roleEntity = await FindRole(toRole);
                        if (roleEntity == null)
                        {
                            return OperationResult.Error(I18N.T("角色 {0} 不存在", toRole));
                        }
                        //角色对应用户
                        var userEntities = IdentityContract.UserRoles.Where(m => m.RoleId == roleEntity.Id).Select(m => m.User).Distinct().ToArray();
                        if (userEntities?.Length > 0)
                        {
                            foreach (var userEntity in userEntities)
                            {
                                receiverUsers.AddIfNotExist(userEntity, o => receiverUsers.Exists(r => r.Id == o.Id));
                            }
                        }
                    }
                }
                //处理消息接受者
                if (receiverUsers.Count > 0)
                {
                    foreach (var receiverUser in receiverUsers)
                    {
                        var messageReceiver = new MessageReceiver()
                        {
                            MessageId = messageEntity.Id,
                            ReceiverId = receiverUser.Id,
                            SendWays = "",
                            LastReadTime = null,
                            LastReadWay = null,
                        };
                        List<MessageSendWay> sendWays = new();
                        foreach (var messageSendWay in messageDto.SendWays)
                        {
                            switch (messageSendWay)
                            {
                                case MessageSendWay.Internal:
                                    sendWays.Add(messageSendWay);
                                    break;
                                case MessageSendWay.Email:
                                    if (!receiverUser.Email.IsMissing() && receiverUser.EmailConfirmed)
                                    {
                                        sendWays.Add(messageSendWay);
                                    }
                                    break;
                                case MessageSendWay.OAuth2:
                                    if (receiverUser.Logins?.Count > 0)
                                    {
                                        sendWays.Add(messageSendWay);
                                    }
                                    break;
                            }
                        }
                        messageReceiver.SendWays = sendWays.ToJsonString();

                        var result2 = await MessageReceiverRepository.InsertAsync(messageReceiver);
                        if (!result2.Succeeded)
                        {
                            return result2;
                        }
                        //处理事件数据
                        eventData.MessageReceivers.Add(messageReceiver);
                        eventData.MessageReceiverUsers.Add(receiverUser);
                    }
                }

                var dateTimeNow = DateTime.Now;
                messageEntity.SendTime = dateTimeNow;
                messageEntity.IsSent = true;
                //处理消息更新
                var result = await MessageRepository.UpdateAsync(messageEntity);
                if (!result.Succeeded)
                {
                    return result;
                }
                //处理消息发送事件数据
                eventData.Messages.Add(messageEntity);
            }
            //触发事件
            if (eventData.Messages.Count > 0 && eventData.MessageReceivers.Count > 0)
            {
                await EventBus?.PublishAsync(eventData);
            }
            return OperationResult.Success();
        }
        #endregion
        #region "获取消息"
        /// <summary>
        /// 获取消息
        /// </summary>
        /// <param name="userId">用户编号</param>
        /// <param name="messageIds">消息编号</param>
        /// <returns>业务操作结果</returns>
        public virtual async Task<OperationResult<MessageDto[]>> GetMessages(long userId = default, params long[] messageIds)
        {
            if (userId <= 0 && Principal?.Identity?.IsAuthenticated == true)
            {
                userId = GetCurrentUserKey().Value;
            }
            Check.GreaterThan(userId, nameof(userId), 0);
            Check.NotNull(messageIds, nameof(messageIds));

            List<MessageDto> messageDtos = new();
            foreach (var messageId in messageIds)
            {
                var messageEntity = await MessageRepository.GetAsync(messageId);
                if (messageEntity == null)
                {
                    return OperationResult.Error(messageDtos.ToArray(), I18N.T("消息记录 {0} 不存在", messageId));
                }
                var messageReceiverEntity = messageEntity.Receivers.FirstOrDefault(o => o.ReceiverId.Equals(userId));
                if (messageReceiverEntity == null)
                {
                    return OperationResult.Error(messageDtos.ToArray(), I18N.T("编号 {0} 接收者 {1} 的消息记录不存在", messageId, userId));
                }

                var messageDto = messageEntity.MapTo<MessageEntity, MessageDto>();
                messageDto.LastReadTime = messageReceiverEntity.LastReadTime;
                messageDto.LastReadWay = messageReceiverEntity.LastReadWay;
                messageDtos.AddIfNotExist(messageDto);
            }
            var result = OperationResult.Success(messageDtos.ToArray());
            return result;
        }
        #endregion
        #region "获取未阅读消息"
        /// <summary>
        /// 获取未阅读消息
        /// </summary>
        /// <param name="userId">用户编号</param>
        /// <returns>业务操作结果</returns>
        public virtual async Task<OperationResult<MessageDtoSimple[]>> GetUnreadMessages(long userId = default)
        {
            if (userId <= 0 && Principal?.Identity?.IsAuthenticated == true)
            {
                userId = GetCurrentUserKey().Value;
            }
            Check.GreaterThan(userId, nameof(userId), 0);

            var messageReceivers = MessageReceiverRepository.QueryAsNoTracking(o => o.ReceiverId.Equals(userId) && o.LastReadTime == null).ToList();
            if (messageReceivers.Count <= 0)
            {
                return OperationResult.Success(Array.Empty<MessageDtoSimple>());
            }
            List<MessageDtoSimple> messageDtos = new();
            foreach (var messageReceiver in messageReceivers)
            {
                var messageDto = messageReceiver.Message.MapTo<MessageEntity, MessageDtoSimple>();
                messageDto.LastReadTime = messageReceiver.LastReadTime;
                messageDto.LastReadWay = messageReceiver.LastReadWay;
                messageDtos.AddIfNotExist(messageDto);
            }
            var result = OperationResult.Success(messageDtos.ToArray());
            return await Task.FromResult(result);
        }
        #endregion
        #region "阅读消息"
        /// <summary>
        /// 阅读消息
        /// </summary>
        /// <param name="readWay">阅读方式</param>
        /// <param name="userId">用户编号</param>
        /// <param name="read">已读/未读</param>
        /// <param name="messageIds">消息编号</param>
        /// <returns>业务操作结果</returns>
        public virtual async Task<OperationResult> ReadMessages(MessageSendWay readWay, long userId, bool read, params long[] messageIds)
        {
            if (userId <= 0 && Principal?.Identity?.IsAuthenticated == true)
            {
                userId = GetCurrentUserKey().Value;
            }
            Check.GreaterThan(userId, nameof(userId), 0);
            Check.NotNull(messageIds, nameof(messageIds));

            var dateTimeNow = DateTime.Now;
            MessageReadEventData eventData = new(SignalRService?.SignalRHub?.Clients, SignalRService?.SignalRHub?.Groups);
            foreach (var messageId in messageIds)
            {
                var messageReceiver = MessageReceiverRepository.QueryAsNoTracking(o => o.MessageId.Equals(messageId) && o.ReceiverId.Equals(userId)).FirstOrDefault();
                if (messageReceiver == null)
                {
                    return OperationResult.Error(I18N.T("编号 {0} 接收者 {1} 的消息记录不存在", messageId, userId));
                }
                if (read)
                {
                    messageReceiver.LastReadTime = dateTimeNow;
                    messageReceiver.LastReadWay = readWay;
                }
                else
                {
                    messageReceiver.LastReadTime = null;
                    messageReceiver.LastReadWay = null;
                }
                var result = await MessageReceiverRepository.UpdateAsync(messageReceiver);
                if (!result.Succeeded)
                {
                    return result;
                }
                var message = MessageRepository.Get(messageId);
                eventData.Messages.AddIfNotExist(message, o => eventData.Messages.Any(r => r.Id == o.Id));
                eventData.MessageReceivers.Add(messageReceiver);
            }
            //触发事件
            if (eventData.Messages.Count > 0 && eventData.MessageReceivers.Count > 0)
            {
                await EventBus?.PublishAsync(eventData);
            }
            return OperationResult.Success();
        }
        #endregion
        #region "删除消息接收者"
        /// <summary>
        /// 删除消息接收者
        /// </summary>
        /// <param name="userId">用户编号</param>
        /// <param name="messageIds">消息编号</param>
        /// <returns>业务操作结果</returns>
        public virtual async Task<OperationResult> DeleteMessageReceiver(long userId, params long[] messageIds)
        {
            if (userId <= 0 && Principal?.Identity?.IsAuthenticated == true)
            {
                userId = GetCurrentUserKey().Value;
            }
            Check.GreaterThan(userId, nameof(userId), 0);
            Check.NotNull(messageIds, nameof(messageIds));

            MessageReceiverDeleteEventData eventData = new(SignalRService?.SignalRHub?.Clients, SignalRService?.SignalRHub?.Groups);
            foreach (var messageId in messageIds)
            {
                var messageEntity = await MessageRepository.GetAsync(messageId);
                if (messageEntity == null)
                {
                    return OperationResult.Error(I18N.T("消息记录 {0} 不存在", messageId));
                }
                var messageReceiverEntity = messageEntity.Receivers.FirstOrDefault(o => o.ReceiverId.Equals(userId));
                if (messageReceiverEntity == null)
                {
                    return OperationResult.Error(I18N.T("编号 {0} 接收者 {1} 的消息记录不存在", messageId, userId));
                }
                var result = await MessageReceiverRepository.DeleteAsync(messageReceiverEntity);
                if (!result.Succeeded)
                {
                    return result;
                }
                //if (messageEntity.Receivers.Count <= 0)
                //{
                //    var result2 = await MessageRepository.DeleteAsync(messageEntity);
                //    if (!result2.Succeeded)
                //    {
                //        return result2;
                //    }
                //}
                eventData.Messages.AddIfNotExist(messageEntity, o => eventData.Messages.Any(r => r.Id == o.Id));
                eventData.MessageReceivers.Add(messageReceiverEntity);
            }
            //触发事件
            if (eventData.Messages.Count > 0 && eventData.MessageReceivers.Count > 0)
            {
                await EventBus?.PublishAsync(eventData);
            }
            return OperationResult.Success();
        }
        #endregion

        #region "创建模板消息"
        /// <summary>
        /// 创建模板消息
        /// </summary>
        /// <param name="dtos">模板消息DTO</param>
        /// <returns>业务操作结果</returns>
        public virtual async Task<OperationResult> CreateTemplateMessages(params TemplateMessageInputDto[] dtos)
        {
            Check.NotNull(dtos, nameof(dtos));
            var method = "MSG_NOTICE";
            TemplateMessageEventData eventData = new(SignalRService?.SignalRHub?.Clients, SignalRService?.SignalRHub?.Groups) { OperateType = OperateType.Insert };
            foreach (var dto in dtos)
            {
                Check.NotNull(dto, nameof(dto));
                Check.NotNullOrEmpty(dto.Title, nameof(dto.Title));

                Check.GreaterThan(dto.StorageDays, nameof(dto.StorageDays), 0, true);
                Check.LessThan(dto.StorageDays, nameof(dto.StorageDays), 365, true);

                switch (dto.MessageType)
                {
                    case MessageType.Text:
                    case MessageType.Image:
                    case MessageType.Voice:
                    case MessageType.Video:
                    case MessageType.File:
                        return OperationResult.Error(I18N.T("模板消息不支持{0}", dto.MessageType.ToDescription()));
                    case MessageType.News:
                        Check.NotNull<object>(dto.Payload, nameof(dto.Payload));
                        break;
                    case MessageType.Data:
                        return OperationResult.Error(I18N.T("模板消息不支持{0}", dto.MessageType.ToDescription()));
                }

                var entity = dto.MapTo<TemplateMessageInputDto, TemplateMessage>();
                entity.Method = method;

                var result = await TemplateMessageRepository.InsertAsync(entity);
                if (!result.Succeeded)
                {
                    return result;
                }
                eventData.TemplateMessages.Add(entity);
            }
            //触发事件
            if (eventData.TemplateMessages.Count > 0)
            {
                await EventBus?.PublishAsync(eventData);
            }
            return OperationResult.Success();
        }
        #endregion
        #region "更新模板消息"
        /// <summary>
        /// 更新模板消息
        /// </summary>
        /// <param name="dtos">模板消息DTO</param>
        /// <returns>业务操作结果</returns>
        public virtual async Task<OperationResult> UpdateTemplateMessages(params TemplateMessageInputDto[] dtos)
        {
            Check.NotNull(dtos, nameof(dtos));
            TemplateMessageEventData eventData = new(SignalRService?.SignalRHub?.Clients, SignalRService?.SignalRHub?.Groups) { OperateType = OperateType.Update };
            foreach (var dto in dtos)
            {
                Check.NotNull(dto, nameof(dto));
                Check.NotNullOrEmpty(dto.Title, nameof(dto.Title));

                Check.GreaterThan(dto.StorageDays, nameof(dto.StorageDays), 0, true);
                Check.LessThan(dto.StorageDays, nameof(dto.StorageDays), 365, true);

                var entity = await TemplateMessageRepository.GetAsync(dto.Id) ?? throw new Exception(I18N.T("模板消息 {0} 不存在", dto.Id));
                switch (dto.MessageType)
                {
                    case MessageType.Text:
                    case MessageType.Image:
                    case MessageType.Voice:
                    case MessageType.Video:
                    case MessageType.File:
                        return OperationResult.Error(I18N.T("查询消息不支持{0}", dto.MessageType.ToDescription()));
                    case MessageType.News:
                        Check.NotNull(dto.Payload, nameof(dto.Payload));
                        break;
                    case MessageType.Data:
                        return OperationResult.Error(I18N.T("查询消息不支持{0}", dto.MessageType.ToDescription()));
                }
                entity = dto.MapTo(entity);

                var result = await TemplateMessageRepository.UpdateAsync(entity);
                if (!result.Succeeded)
                {
                    return result;
                }
                eventData.TemplateMessages.Add(entity);
            }
            //触发事件
            if (eventData.TemplateMessages.Count > 0)
            {
                await EventBus?.PublishAsync(eventData);
            }
            return OperationResult.Success();
        }
        #endregion
        #region "删除模板消息"
        /// <summary>
        /// 删除模板消息
        /// </summary>
        /// <param name="ids">消息编号</param>
        /// <returns>业务操作结果</returns>
        public virtual async Task<OperationResult> DeleteTemplateMessages(params long[] ids)
        {
            Check.NotNull(ids, nameof(ids));
            TemplateMessageEventData eventData = new(SignalRService?.SignalRHub?.Clients, SignalRService?.SignalRHub?.Groups) { OperateType = OperateType.Delete };
            foreach (var id in ids)
            {
                var entity = await TemplateMessageRepository.GetAsync(id);
                if (entity == null)
                {
                    throw new Exception(I18N.T("模板消息 {0} 不存在", id));
                }

                var result = await TemplateMessageRepository.DeleteAsync(entity);
                if (!result.Succeeded)
                {
                    return result;
                }
                eventData.TemplateMessages.Add(entity);
            }
            //触发事件
            if (eventData.TemplateMessages.Count > 0)
            {
                await EventBus?.PublishAsync(eventData);
            }
            return OperationResult.Success();
        }
        #endregion
        #region "发送模板消息"
        /// <summary>
        /// 发送模板消息
        /// </summary>
        /// <param name="messageIds">消息编号</param>
        /// <returns>业务操作结果</returns>
        public virtual async Task<OperationResult> SendTemplateMessages(params long[] messageIds)
        {
            Check.NotNull(messageIds, nameof(messageIds));

            foreach (var messageId in messageIds)
            {
                Check.GreaterThan(messageId, nameof(messageId), 0);
                var messageEntity = await TemplateMessageRepository.GetAsync(messageId);
                if (messageEntity == null)
                {
                    return OperationResult.Error(I18N.T("模板消息 {0} 不存在", messageId));
                }
                var messageDto = messageEntity.MapTo<TemplateMessage, TemplateMessageOutputDto>();
                Check.NotNullOrEmpty(messageDto.Title, nameof(messageDto.Title));
                Check.NotNullOrEmpty(messageDto.Content, nameof(messageDto.Content));
                if (messageDto.SendWays?.Length <= 0)
                {
                    return OperationResult.Error(I18N.T("没有发送方式"));
                }
                if (messageDto.ToUsers?.Length <= 0 && messageDto.ToOrganizations?.Length <= 0 && messageDto.ToRoles?.Length <= 0)
                {
                    return OperationResult.Error(I18N.T("没有收件人信息"));
                }
                Check.NotNullOrEmpty(messageDto.Title, nameof(messageDto.Title));
                Check.NotNullOrEmpty(messageDto.Content, nameof(messageDto.Content));

                //发送消息
                MessageInputDto messageInput = new()
                {
                    BaseType = nameof(TemplateMessage),
                    BaseId = messageDto.Id.ToString(),
                    Method = messageDto.Method,
                    Icon = messageDto.Icon,
                    MessageType = messageDto.MessageType,
                    MessageLevel = messageDto.MessageLevel,
                    Title = messageDto.Title,
                    Content = messageDto.Content,
                    Payload = messageDto.Payload,
                    SendTime = DateTime.Now,
                    SendWays = messageDto.SendWays,
                    ToUsers = messageDto.ToUsers,
                    ToOrganizations = messageDto.ToOrganizations,
                    ToRoles = messageDto.ToRoles,
                    StorageDays = messageDto.StorageDays,
                };
                IUnitOfWork unitOfWork = ServiceProvider.GetUnitOfWork(true);
                //创建消息
                var result = await CreateMessages(messageInput);
                if (!result.Succeeded)
                {
                    return result;
                }
                //更新查询消息
                messageEntity.NextSendTime = CronHelper.GetNextDateTime(messageEntity.CronExpression);
                result = await TemplateMessageRepository.UpdateAsync(messageEntity);
                if (!result.Succeeded)
                {
                    return result;
                }
                await unitOfWork.CommitAsync();
            }

            return OperationResult.Success();
        }
        #endregion

        #region "获取组织机构组键"
        /// <summary>
        /// 获取组织机构组键
        /// </summary>
        /// <param name="key">键值</param>
        /// <returns>组织机构组键</returns>
        public virtual string GetGroupKeyByOrganization(string key)
        {
            return $"Group:Organization:{key}";
        }
        #endregion
        #region "获取角色组键"
        /// <summary>
        /// 获取角色组键
        /// </summary>
        /// <param name="key">键值</param>
        /// <returns>角色组键</returns>
        public virtual string GetGroupKeyByRole(string key)
        {
            return $"Group:Role:{key}";
        }
        #endregion
        #region "获取消息发送任务编号"
        /// <summary>
        /// 获取消息发送任务编号
        /// </summary>
        /// <param name="key">键值</param>
        /// <returns>消息发送任务编号</returns>
        public virtual string GetMessageSendJobId(string key)
        {
            return $"Message:Send:{key}";
        }
        #endregion
        #region "获取消息删除任务编号"
        /// <summary>
        /// 获取消息删除任务编号
        /// </summary>
        /// <param name="key">键值</param>
        /// <returns>消息删除任务编号</returns>
        public virtual string GetMessageDeleteJobId(string key)
        {
            return $"Message:Delete:{key}";
        }
        #endregion
        #region "获取消息查询任务编号"
        /// <summary>
        /// 获取消息查询任务编号
        /// </summary>
        /// <param name="key">键值</param>
        /// <returns>消息查询任务编号</returns>
        public virtual string GetMessageQueryJobId(string key)
        {
            return $"Message:Query:{key}";
        }
        #endregion
        #region "获取消息模板任务编号"
        /// <summary>
        /// 获取消息模板任务编号
        /// </summary>
        /// <param name="key">键值</param>
        /// <returns>消息模板任务编号</returns>
        public virtual string GetMessageTemplateJobId(string key)
        {
            return $"Message:Template:{key}";
        }
        #endregion

        #endregion

        #region 受保护方法
        /// <summary>
        /// 获取当前用户标识
        /// </summary>
        /// <returns></returns>
        protected virtual long? GetCurrentUserKey()
        {
            //获取用户Id信息
            var userKey = Principal?.Identity?.GetUserId<long>();
            return userKey;
        }

        /// <summary>
        /// 依次按用户编号、用户名，Email、手机查找用户
        /// </summary>
        /// <param name="account">账号</param>
        /// <returns></returns>
        protected virtual async Task<User> FindUser(string account)
        {
            User user = await UserManager.FindByIdAsync(account);
            if (user != null)
            {
                return user;
            }
            user = await UserManager.FindByNameAsync(account);
            if (user != null)
            {
                return user;
            }
            if (account.IsEmail())
            {
                user = await UserManager.FindByEmailAsync(account);
                if (user != null)
                {
                    return user;
                }
            }
            if (account.IsMobileNumber())
            {
                user = UserManager.Users.FirstOrDefault(m => m.PhoneNumber == account);
                if (user != null)
                {
                    return user;
                }
            }
            return user;
        }

        /// <summary>
        /// 依次按编号、名称查找角色
        /// </summary>
        /// <param name="account">账号</param>
        /// <returns></returns>
        protected virtual async Task<Role> FindRole(string account)
        {
            Role role = await RoleManager.FindByIdAsync(account);
            if (role != null)
            {
                return role;
            }
            role = await RoleManager.FindByNameAsync(account);
            if (role != null)
            {
                return role;
            }
            return role;
        }

        #endregion

    }

}
